package servlet;

import it.polimi.swimv2.entities.Ability;
import it.polimi.swimv2.entities.HelpRequest;
import it.polimi.swimv2.exception.HelpRequestException;
import it.polimi.swimv2.exception.UserNotFoundException;
import it.polimi.swimv2.remote.AbilityManagerRemote;
import it.polimi.swimv2.remote.FriendshipRequestManagerRemote;
import it.polimi.swimv2.remote.HelpRequestManagerRemote;
import it.polimi.swimv2.remote.UserProfileManagerRemote;
import it.polimi.swimv2.util.RemoteBindingName;

import java.io.IOException;
import java.util.Collection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class HelpRequestServlet
 */
public class HelpRequestServlet extends HttpServlet {		
	
	
	// Actions performed by this servlet:
	private static final String SHOW_REQUEST_FORM = "showRequestForm";
	private static final String SHOW_REQUEST_DETAILS = "showRequestDetails";
	private static final String SHOW_REQUESTS_LIST = "showRequestsList";
	private static final String CANCEL_REQUEST_ACT = "cancelRequest";
	private static final String REFUSE_REQUEST_ACT = "refuseRequest";
	private static final String ACCEPT_REQUEST_ACT = "acceptRequest";
	private static final String REMOVE_REQUEST = "removeRequest";
	private static final String SEND_REQUEST_ACT = "sendRequest";
	private static final String SEND_MESSAGE = "sendMessage";
	// Page references:
	private static final String LOGIN_FORM_JSP = "loginForm.jsp";
	private static final String HELP_REQUEST_DETAILS_JSP = "helpRequestDetails.jsp";
	private static final String ERROR_JSP = "error.jsp";
	private static final String INDEX_JSP = "index.jsp";
	private static final String HELP_REQUEST_FORM_JSP = "helpRequestForm.jsp";
	private static final String HELP_REQUESTS_JSP = "helpRequestsList.jsp";
	// Parameters HttpRequest:
	private static final String RQ_ID = "rqID";
	private static final String SENT_REQUESTS = "sentRequests";
	private static final String RECEIVED_REQUESTS = "receivedRequests";
	private static final String REQUEST = "request";
	private static final String SESSION_USERNAME = "user";
	private static final String MESSAGE_REQPARAM = "message";
	private static final String RECEIVER_USERNAME_REQPARAM = "receiver";
	private static final String DECLARED_ABILITIES_REQPARAM = "declaredAbilities";
	private static final String OBJECT_REQPARAM = "object";
	private static final String ABILITY_NAME_REQPARAM = "abilityName";
	
	private static final String HELP_REQUEST = "helpRequest";

	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public HelpRequestServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		manageHttpRequest(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		manageHttpRequest(request, response);
	}
	/**
	 * manages the action requested by http request
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void manageHttpRequest(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		String act = request.getParameter("act");
		HttpSession session = request.getSession();
		String username = (String) session.getAttribute(SESSION_USERNAME);
		if(username==null){
			response.sendRedirect(LOGIN_FORM_JSP);
			return;
		}
		if (act == null) {
			response.sendRedirect(INDEX_JSP);
			return;
		}
		if (act.equals(SEND_REQUEST_ACT)) {
			processSendRequest(request,response);
		} else if (act.equals(ACCEPT_REQUEST_ACT)) {
			processAcceptRequest(request,response);
		} else if (act.equals(REFUSE_REQUEST_ACT)) {
			processRefuseRequest(request,response);
		} else if (act.equals(CANCEL_REQUEST_ACT)) {
			processCancelRequest(request,response);
		} else if (act.equals(REMOVE_REQUEST)) {
			processRemoveRequest(request,response);
		} else if (act.equals(SHOW_REQUESTS_LIST)) {
			showRequestList(request,response);
		} else if (act.equals(SHOW_REQUEST_DETAILS)) {
			showRequestDetails(request,response);
		} else if (act.equals(SHOW_REQUEST_FORM)) {
			showRequestForm(request, response);
		}  else if (act.equals(SEND_MESSAGE)) {
			processSendMessage(request, response);
		}else {
			response.sendRedirect(INDEX_JSP);
		}
	}
	
	/**
	 * manages the sending of a new message
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processSendMessage(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try{
			HelpRequestManagerRemote rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String sender = (String) session.getAttribute(SESSION_USERNAME);
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			String message = request.getParameter(MESSAGE_REQPARAM);
			if(message!=null && !message.equals("")){
				rem.attachMessage(sender, rqID, message);
			}
			showRequestDetails(request, response);		
		}catch(NamingException e){
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
		
		
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void showRequestForm(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		try {
			UserProfileManagerRemote rem=retrieveUserProfileManagerRemote();
			String receiver = request.getParameter(RECEIVER_USERNAME_REQPARAM);
			if (receiver!=null){
				Collection<Ability> declaredAbilities = rem.getUserDetail(receiver).getDeclaredAbilities();
				request.setAttribute(DECLARED_ABILITIES_REQPARAM, declaredAbilities);
				request.setAttribute("receiverUsername", receiver);
				RequestDispatcher dispatcher = request.getRequestDispatcher(HELP_REQUEST_FORM_JSP);
				dispatcher.forward(request, response);
			}else{
				response.sendRedirect(INDEX_JSP);
			}
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (UserNotFoundException e) {
			response.sendRedirect(ERROR_JSP);
		}

	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showRequestDetails(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		try {
			HelpRequestManagerRemote rem = retrieveHelpRequestManagerRemote();
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			HelpRequest req = rem.getHelpRequest(rqID);
			request.setAttribute(HELP_REQUEST, req);
			RequestDispatcher dispatcher = request.getRequestDispatcher(HELP_REQUEST_DETAILS_JSP);
			dispatcher.forward(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} 
	}
	/**
	 * shows the list of all help requests
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void showRequestList(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String username=(String) session.getAttribute(SESSION_USERNAME);
			Collection<HelpRequest> receivedRequests = rem.getReceivedHelpRequest(username);
			Collection<HelpRequest> sentRequests = rem.getSentHelpRequest(username);
			request.setAttribute(RECEIVED_REQUESTS, receivedRequests);
			request.setAttribute(SENT_REQUESTS, sentRequests);
			RequestDispatcher dispatcher = request.getRequestDispatcher(HELP_REQUESTS_JSP);
			dispatcher.forward(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * deletes a non-pending request from the list
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void processRemoveRequest(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String username=(String) session.getAttribute(SESSION_USERNAME);
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			rem.removeHelpRequest(rqID, username);
			showRequestList(request, response);			
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}		
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processCancelRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String username=(String) session.getAttribute(SESSION_USERNAME);
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			rem.deleteHelp(username, rqID);
			showRequestDetails(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processRefuseRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String username=(String) session.getAttribute(SESSION_USERNAME);
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			rem.refuseHelp(username, rqID);
			showRequestDetails(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void processAcceptRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String username=(String) session.getAttribute(SESSION_USERNAME);
			Integer rqID = Integer.parseInt(request.getParameter(RQ_ID));
			rem.acceptHelp(username, rqID);
			showRequestDetails(request, response);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void processSendRequest(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		HelpRequestManagerRemote rem;
		try {
			rem = retrieveHelpRequestManagerRemote();
			HttpSession session = request.getSession();
			String senderUsername=(String) session.getAttribute(SESSION_USERNAME);
			String receiverUsername=request.getParameter(RECEIVER_USERNAME_REQPARAM);
			String requiredAbility = request.getParameter(ABILITY_NAME_REQPARAM);
			String object=request.getParameter(OBJECT_REQPARAM);
			String message=request.getParameter(MESSAGE_REQPARAM);
			if(requiredAbility==null||requiredAbility.equals("")){
				request.setAttribute("missAbility", "missed");
				showRequestForm(request, response);
				return;
			}
			int id=rem.sendHelpRequest(senderUsername, receiverUsername, requiredAbility, object);
			if(message!=null&&message.length()>0){
				rem.attachMessage(senderUsername, id, message);
			}
			request.setAttribute("sendSuccess", "ok");
			request.setAttribute("receiverUsername", receiverUsername);
			showRequestForm(request, response);		
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (HelpRequestException e) {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * retrieves the remote object
	 * @return
	 * @throws NamingException
	 */
	private UserProfileManagerRemote retrieveUserProfileManagerRemote()
			throws NamingException {
		Context jndiContext = new InitialContext();
		Object ref = jndiContext.lookup(RemoteBindingName.USER_PROFILE_MANAGER);
		UserProfileManagerRemote rem = (UserProfileManagerRemote) ref;
		return rem;
	}
	/**
	 * retrieves the remote object
	 * @return
	 * @throws NamingException
	 */
	private HelpRequestManagerRemote retrieveHelpRequestManagerRemote()
			throws NamingException {
		Context jndiContext = new InitialContext();
		Object ref = jndiContext.lookup(RemoteBindingName.HELP_REQUEST_MANAGER);
		HelpRequestManagerRemote rem = (HelpRequestManagerRemote) ref;
		return rem;
	}
	
}
